﻿namespace Pub.Class
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Runtime.Serialization.Formatters.Soap;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Web.Script.Serialization;
    using System.Xml.Serialization;

    public static class ObjectExtensions
    {
        public static void CheckOnNull(this object obj, string parameterName)
        {
            if (obj.IsNull())
            {
                throw new ArgumentNullException(parameterName);
            }
        }

        public static void CheckOnNull(this object obj, string parameterName, string message)
        {
            if (obj.IsNull())
            {
                throw new ArgumentNullException(parameterName, message);
            }
        }

        public static T ConvertTo<T>(this object value)
        {
            return value.ConvertTo<T>(default(T));
        }

        public static T ConvertTo<T>(this object value, T defaultValue)
        {
            if (value.IsNotNull())
            {
                Type destinationType = typeof(T);
                TypeConverter converter = TypeDescriptor.GetConverter(value);
                if (converter.IsNotNull() && converter.CanConvertTo(destinationType))
                {
                    return (T) converter.ConvertTo(value, destinationType);
                }
                converter = TypeDescriptor.GetConverter(destinationType);
                if (!converter.IsNotNull())
                {
                    return defaultValue;
                }
                try
                {
                    if (converter.CanConvertFrom(value.GetType()))
                    {
                        return (T) converter.ConvertFrom(value);
                    }
                }
                catch
                {
                    return default(T);
                }
            }
            return defaultValue;
        }

        public static T ConvertTo<T>(this object value, T defaultValue, bool ignoreException)
        {
            if (ignoreException)
            {
                try
                {
                    return value.ConvertTo<T>();
                }
                catch
                {
                    return defaultValue;
                }
            }
            return value.ConvertTo<T>();
        }

        public static T FromCache<T>(this string key)
        {
            return (T) Cache2.Get(key);
        }

        public static T GetAttribute<T>(this object obj) where T: Attribute
        {
            return obj.GetAttribute<T>(true);
        }

        public static T GetAttribute<T>(this object obj, bool includeInherited) where T: Attribute
        {
            if (obj is PropertyInfo)
            {
                object[] objArray = (obj as PropertyInfo).GetCustomAttributes(typeof(T), includeInherited);
                if (objArray.IsNotNull() && (objArray.Length > 0))
                {
                    return (objArray[0] as T);
                }
                return default(T);
            }
            if (obj is FieldInfo)
            {
                object[] objArray2 = (obj as FieldInfo).GetCustomAttributes(typeof(T), includeInherited);
                if (objArray2.IsNotNull() && (objArray2.Length > 0))
                {
                    return (objArray2[0] as T);
                }
                return default(T);
            }
            if (obj is MemberInfo)
            {
                object[] objArray3 = (obj as MemberInfo).GetCustomAttributes(typeof(T), includeInherited);
                if (objArray3.IsNotNull() && (objArray3.Length > 0))
                {
                    return (objArray3[0] as T);
                }
                return default(T);
            }
            if (obj is EventInfo)
            {
                object[] objArray4 = (obj as EventInfo).GetCustomAttributes(typeof(T), includeInherited);
                if (objArray4.IsNotNull() && (objArray4.Length > 0))
                {
                    return (objArray4[0] as T);
                }
                return default(T);
            }
            if (obj is MethodInfo)
            {
                object[] objArray5 = (obj as MethodInfo).GetCustomAttributes(typeof(T), includeInherited);
                if (objArray5.IsNotNull() && (objArray5.Length > 0))
                {
                    return (objArray5[0] as T);
                }
                return default(T);
            }
            object[] customAttributes = ((obj as Type) ?? obj.GetType()).GetCustomAttributes(typeof(T), includeInherited);
            if (customAttributes.IsNotNull() && (customAttributes.Length > 0))
            {
                return (customAttributes[0] as T);
            }
            return default(T);
        }

        public static IEnumerable<T> GetAttributes<T>(this object obj) where T: Attribute
        {
            return obj.GetAttributes<T>();
        }

        public static IEnumerable<T> GetAttributes<T>(this object obj, bool includeInherited) where T: Attribute
        {
            if (obj is PropertyInfo)
            {
                foreach (object iteratorVariable0 in (obj as PropertyInfo).GetCustomAttributes(typeof(T), includeInherited))
                {
                    if (iteratorVariable0 is T)
                    {
                        yield return (T) iteratorVariable0;
                    }
                }
            }
            else if (obj is FieldInfo)
            {
                foreach (object iteratorVariable1 in (obj as FieldInfo).GetCustomAttributes(typeof(T), includeInherited))
                {
                    if (iteratorVariable1 is T)
                    {
                        yield return (T) iteratorVariable1;
                    }
                }
            }
            else if (obj is MemberInfo)
            {
                foreach (object iteratorVariable2 in (obj as MemberInfo).GetCustomAttributes(typeof(T), includeInherited))
                {
                    if (iteratorVariable2 is T)
                    {
                        yield return (T) iteratorVariable2;
                    }
                }
            }
            else if (obj is EventInfo)
            {
                foreach (object iteratorVariable3 in (obj as EventInfo).GetCustomAttributes(typeof(T), includeInherited))
                {
                    if (iteratorVariable3 is T)
                    {
                        yield return (T) iteratorVariable3;
                    }
                }
            }
            else if (obj is MethodInfo)
            {
                foreach (object iteratorVariable4 in (obj as MethodInfo).GetCustomAttributes(typeof(T), includeInherited))
                {
                    if (iteratorVariable4 is T)
                    {
                        yield return (T) iteratorVariable4;
                    }
                }
            }
            Type iteratorVariable5 = (obj as Type) ?? obj.GetType();
            foreach (object iteratorVariable6 in iteratorVariable5.GetCustomAttributes(typeof(T), includeInherited))
            {
                if (iteratorVariable6 is T)
                {
                    yield return (T) iteratorVariable6;
                }
            }
        }

        public static object GetPropertyValue(this object obj, string propertyName)
        {
            return obj.GetPropertyValue<object>(propertyName, null);
        }

        public static T GetPropertyValue<T>(this object obj, string propertyName)
        {
            return obj.GetPropertyValue<T>(propertyName, default(T));
        }

        public static T GetPropertyValue<T>(this object obj, string propertyName, T defaultValue)
        {
            PropertyInfo propertyCache = obj.GetType().GetPropertyCache(propertyName);
            if (propertyCache.IsNull())
            {
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);
            }
            object obj2 = propertyCache.GetValue(obj, null);
            if (obj2 is T)
            {
                return (T) obj2;
            }
            return defaultValue;
        }

        public static bool InstanceOf<T>(this object value)
        {
            return (value is T);
        }

        public static T InvokeMethod<T>(this object obj, string methodName)
        {
            return obj.InvokeMethod<T>(methodName, null);
        }

        public static object InvokeMethod(this object obj, string methodName, params object[] parameters)
        {
            return obj.InvokeMethod<object>(methodName, parameters);
        }

        public static T InvokeMethod<T>(this object obj, string methodName, params object[] parameters)
        {
            MethodInfo method = obj.GetType().GetMethod(methodName);
            if (method.IsNull())
            {
                throw new ArgumentException(string.Format("找不到方法“{0}”！", methodName), methodName);
            }
            object obj2 = method.Invoke(obj, parameters);
            if (obj2 is T)
            {
                return (T) obj2;
            }
            return default(T);
        }

        public static bool IsAllNull(this object obj)
        {
            if (!obj.IsNull())
            {
                return obj.IsDBNull();
            }
            return true;
        }

        public static bool IsArray(this object obj)
        {
            return obj.IsType(typeof(Array));
        }

        public static bool IsDBNull(this object obj)
        {
            return obj.IsType(typeof(DBNull));
        }

        public static T IsDBNull<T>(this object obj, T t)
        {
            if (!obj.IsType(typeof(DBNull)))
            {
                return (T) obj;
            }
            return t;
        }

        public static bool IsNotAllNull(this object obj)
        {
            return (!obj.IsNull() && !obj.IsDBNull());
        }

        public static bool IsNotDBNull(this object obj)
        {
            return !obj.IsDBNull();
        }

        public static bool IsNotNull(this object obj)
        {
            return !obj.IsNull();
        }

        public static bool IsNotNullEquals(this object o1, object o2)
        {
            return ((o1 == o2) || (o1.IsNotNull() && o1.Equals(o2)));
        }

        public static bool IsNull(this object obj)
        {
            return (null == obj);
        }

        public static T IsNull<T>(this object obj, T t)
        {
            if (!obj.IsNull())
            {
                return (T) obj;
            }
            return t;
        }

        public static bool IsNullEmpty(this object obj)
        {
            return (null == obj);
        }

        public static bool IsType(this object obj, Type type)
        {
            return obj.GetType().Equals(type);
        }

        public static T SafeCast<T>(this object value)
        {
            if (value is T)
            {
                return value.UnsafeCast<T>();
            }
            return default(T);
        }

        public static string SafeSql(this object obj)
        {
            string str = obj.ToString();
            str = str.IsNullEmpty() ? "" : str.Replace("'", "''");
            str = new Regex("exec", RegexOptions.IgnoreCase).Replace(str, "&#101;xec");
            str = new Regex("xp_cmdshell", RegexOptions.IgnoreCase).Replace(str, "&#120;p_cmdshell");
            str = new Regex("select", RegexOptions.IgnoreCase).Replace(str, "&#115;elect");
            str = new Regex("insert", RegexOptions.IgnoreCase).Replace(str, "&#105;nsert");
            str = new Regex("update", RegexOptions.IgnoreCase).Replace(str, "&#117;pdate");
            str = new Regex("delete", RegexOptions.IgnoreCase).Replace(str, "&#100;elete");
            str = new Regex("drop", RegexOptions.IgnoreCase).Replace(str, "&#100;rop");
            str = new Regex("create", RegexOptions.IgnoreCase).Replace(str, "&#99;reate");
            str = new Regex("rename", RegexOptions.IgnoreCase).Replace(str, "&#114;ename");
            str = new Regex("truncate", RegexOptions.IgnoreCase).Replace(str, "&#116;runcate");
            str = new Regex("alter", RegexOptions.IgnoreCase).Replace(str, "&#97;lter");
            str = new Regex("exists", RegexOptions.IgnoreCase).Replace(str, "&#101;xists");
            str = new Regex("master.", RegexOptions.IgnoreCase).Replace(str, "&#109;aster.");
            return new Regex("restore", RegexOptions.IgnoreCase).Replace(str, "&#114;estore");
        }

        public static string SafeSqlSimple(this object obj)
        {
            string str = obj.ToString();
            return (str.IsNullEmpty() ? "" : str.Replace("'", "''"));
        }

        public static void SetPropertyValue(this object obj, string propertyName, object value)
        {
            PropertyInfo propertyCache = obj.GetType().GetPropertyCache(propertyName);
            if (propertyCache.IsNull())
            {
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);
            }
            propertyCache.SetValue(obj, value, null);
        }

        public static long ToBigInt(this object strValue)
        {
            return strValue.ToBigInt(0L);
        }

        public static long ToBigInt(this object strValue, long defValue)
        {
            long result = 0L;
            long.TryParse(strValue.ToStr(), out result);
            if (result != 0L)
            {
                return result;
            }
            return defValue;
        }

        public static byte[] ToBinary(this object value)
        {
            MemoryStream serializationStream = new MemoryStream();
            new BinaryFormatter().Serialize(serializationStream, value);
            return serializationStream.ToArray();
        }

        public static bool ToBool(this object strValue)
        {
            return strValue.ToBool(false);
        }

        public static bool ToBool(this object strValue, bool defValue)
        {
            if (strValue.IsNotNull() || strValue.IsNotDBNull())
            {
                if (string.Compare(strValue.ToStr(), "true", true) == 0)
                {
                    return true;
                }
                if (string.Compare(strValue.ToStr(), "false", true) == 0)
                {
                    return false;
                }
                if (string.Compare(strValue.ToStr(), "1", true) == 0)
                {
                    return true;
                }
                if (string.Compare(strValue.ToStr(), "0", true) == 0)
                {
                    return false;
                }
            }
            return defValue;
        }

        public static void ToCache(this object value, string key)
        {
            Cache2.Insert(key, value);
        }

        public static decimal ToDecimal(this object strValue)
        {
            return strValue.ToDecimal(0M);
        }

        public static decimal ToDecimal(this object strValue, decimal defValue)
        {
            decimal result = 0M;
            decimal.TryParse(strValue.ToStr(), out result);
            if (!(result == 0M))
            {
                return result;
            }
            return defValue;
        }

        public static string ToExceptionDetail(this Exception ex)
        {
            return Safe.Expand(ex);
        }

        public static void ToFile(this Exception ex, string fileName)
        {
            Pub.Class.Log.Write(fileName, ex.ToExceptionDetail());
        }

        public static float ToFloat(this object strValue)
        {
            return strValue.ToFloat(0f);
        }

        public static float ToFloat(this object strValue, float defValue)
        {
            float result = 0f;
            float.TryParse(strValue.ToStr(), out result);
            if (result != 0f)
            {
                return result;
            }
            return defValue;
        }

        public static int ToInt(this object strValue)
        {
            return strValue.ToInt(0);
        }

        public static int ToInt(this object strValue, int defValue)
        {
            int result = 0;
            int.TryParse(strValue.ToStr(), out result);
            if (result != 0)
            {
                return result;
            }
            return defValue;
        }

        public static int ToInteger(this object strValue)
        {
            return strValue.ToInteger(0);
        }

        public static int ToInteger(this object strValue, int defValue)
        {
            int result = 0;
            int.TryParse(strValue.ToStr(), out result);
            if (result != 0)
            {
                return result;
            }
            return defValue;
        }

        public static string ToJson(this object obj)
        {
            return obj.ToJson(null);
        }

        public static string ToJson(this object obj, IEnumerable<JavaScriptConverter> jsonConverters)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(obj);
        }

        public static MemoryStream ToMemoryStream(this object request)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream serializationStream = new MemoryStream();
            formatter.Serialize(serializationStream, request);
            return serializationStream;
        }

        public static decimal ToMoney(this object strValue)
        {
            return strValue.ToMoney(0M);
        }

        public static decimal ToMoney(this object strValue, decimal defValue)
        {
            decimal result = 0M;
            decimal.TryParse(strValue.ToStr(), out result);
            if (!(result == 0M))
            {
                return result;
            }
            return defValue;
        }

        public static string ToNVarChar(this object strValue)
        {
            return strValue.ToStr();
        }

        public static short ToSmallInt(this object strValue)
        {
            return strValue.ToSmallInt(0);
        }

        public static short ToSmallInt(this object strValue, short defValue)
        {
            short result = 0;
            short.TryParse(strValue.ToStr(), out result);
            if (result != 0)
            {
                return result;
            }
            return defValue;
        }

        public static string ToSoap(this object obj)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                new SoapFormatter().Serialize(stream, obj);
                stream.Flush();
                return new UTF8Encoding().GetString(stream.GetBuffer(), 0, (int) stream.Position);
            }
        }

        public static string ToStr(this object strValue)
        {
            if (!strValue.IsNull() && !strValue.IsDBNull())
            {
                return strValue.ToString();
            }
            return string.Empty;
        }

        public static byte ToTinyInt(this object strValue)
        {
            return strValue.ToTinyInt(0);
        }

        public static byte ToTinyInt(this object strValue, byte defValue)
        {
            byte result = 0;
            byte.TryParse(strValue.ToStr(), out result);
            if (result != 0)
            {
                return result;
            }
            return defValue;
        }

        public static T ToType<T>(this object value)
        {
            return (T) value;
        }

        public static string ToVarChar(this object strValue)
        {
            return strValue.ToStr();
        }

        public static string ToXml(this object o)
        {
            XmlSerializer serializer = new XmlSerializer(o.GetType());
            StringBuilder sb = new StringBuilder();
            using (TextWriter writer = new StringWriter(sb))
            {
                serializer.Serialize(writer, o);
            }
            return sb.ToString();
        }

        public static string ToXml(this object source, Encoding encoding)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                new XmlSerializer(source.GetType()).Serialize((Stream) stream, source);
                stream.Position = 0L;
                return encoding.GetString(stream.ToArray());
            }
        }

        public static void ToXmlFile(this object o, string fileName)
        {
            XmlSerializer serializer = new XmlSerializer(o.GetType());
            using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                serializer.Serialize((Stream) stream, o);
            }
        }

        public static T UnsafeCast<T>(this object value)
        {
            if (!value.IsNull())
            {
                return (T) value;
            }
            return default(T);
        }

        public static void Write(this object o)
        {
            Msg.Write(o);
        }

        public static void WriteEnd(this object o)
        {
            Msg.WriteEnd(o);
        }
    }
}

